#include "CRendererOGL.h"
#include "CRenderTargetOGL.h"
#include "IInstance.h"
#include "CInputSystemSDL.h"
#include "CVertexBufferOGL.h"

IRenderer* 	RENDERER = NULL;
SURFACE*		BACKBUFFER = NULL;
CInputSystemSDL* INPUT = NULL;

/// ENTRY POINT
int main( int, char ** ) {

	RENDERER = new CRendererOGL( );
	if( !RENDERER->Initialize( 800, 600, 32, false ) ) return -1;
	SDL_ShowCursor(SDL_DISABLE);

	BACKBUFFER = RENDERER->GetBackBuffer( );
	IInstance* CAMERA = BACKBUFFER->Camera( );

	INPUT = new CInputSystemSDL( );
	INPUT->Initialize( );

	uint counter = 0;


	tzmVertexPNT vertices[24];
   // Front Face
	vertices[0] = tzmVertexPNT( -1.0f, -1.0f,  1.0f,  0, 0, 1.0f,   0,     0  );
	vertices[1] = tzmVertexPNT(  1.0f, -1.0f,  1.0f,  0, 0, 1.0f, 1.0f,    0  );
	vertices[2] = tzmVertexPNT(  1.0f,  1.0f,  1.0f,  0, 0, 1.0f, 1.0f,  1.0f );
	vertices[3] = tzmVertexPNT( -1.0f,  1.0f,  1.0f,  0, 0, 1.0f,   0,   1.0f );
   // Back Face
	vertices[4] = tzmVertexPNT( -1.0f, -1.0f, -1.0f,  0,  0,  -1.0f,  1.0f,    0  );
	vertices[5] = tzmVertexPNT( -1.0f,  1.0f, -1.0f,  0,  0,  -1.0f,  1.0f,  1.0f );
	vertices[6] = tzmVertexPNT(  1.0f,  1.0f, -1.0f,  0,  0,  -1.0f,    0,   1.0f );
	vertices[7] = tzmVertexPNT(  1.0f, -1.0f, -1.0f,  0,  0,  -1.0f,    0,     0  );
   // Top Face
	vertices[8] = tzmVertexPNT(  -1.0f,  1.0f, -1.0f,  0,  1.0f,  0,    0,   1.0f );
	vertices[9] = tzmVertexPNT(  -1.0f,  1.0f,  1.0f,  0,  1.0f,  0,    0,     0  );
	vertices[10] = tzmVertexPNT(  1.0f,  1.0f,  1.0f,  0,  1.0f,  0,  1.0f,    0  );
	vertices[11] = tzmVertexPNT(  1.0f,  1.0f, -1.0f,  0,  1.0f,  0,  1.0f,  1.0f );
   // Bottom Face
	vertices[12] = tzmVertexPNT( -1.0f, -1.0f, -1.0f,  0, -1.0f,  0,  1.0f,    1.0f );
	vertices[13] = tzmVertexPNT(  1.0f, -1.0f, -1.0f,  0, -1.0f,  0,    0,     1.0f );
	vertices[14] = tzmVertexPNT(  1.0f, -1.0f,  1.0f,  0, -1.0f,  0,    0,       0 );
	vertices[15] = tzmVertexPNT( -1.0f, -1.0f,  1.0f,  0, -1.0f,  0,  1.0f,      0 );
   // Right Face
	vertices[16] = tzmVertexPNT(  1.0f, -1.0f, -1.0f,  1.0f, 0,  0,  1.0f,    0);
	vertices[17] = tzmVertexPNT(  1.0f,  1.0f, -1.0f,  1.0f, 0,  0,  1.0f,  1.0f);
	vertices[18] = tzmVertexPNT(  1.0f,  1.0f,  1.0f,  1.0f, 0,  0,    0,   1.0f);
	vertices[19] = tzmVertexPNT(  1.0f, -1.0f,  1.0f,  1.0f, 0,  0,    0,     0);
   // Left Face
	vertices[20] = tzmVertexPNT( -1.0f, -1.0f, -1.0f,  -1.0f, 0,  0,    0,     0);
	vertices[21] = tzmVertexPNT( -1.0f, -1.0f,  1.0f,  -1.0f, 0,  0,  1.0f,    0);
	vertices[22] = tzmVertexPNT( -1.0f,  1.0f,  1.0f,  -1.0f, 0,  0,  1.0f,  1.0f);
	vertices[23] = tzmVertexPNT( -1.0f,  1.0f, -1.0f,  -1.0f, 0,  0,    0,   1.0f);

	CVertexBufferOGL* buffer = new CVertexBufferOGL( VPT_QUADS, 24, (byte*)vertices, POS|NOR|TEX );

	if( buffer->IsInvalid( ) )
      return 0;

	/// ENTER LOOP
	bool non_stop = true;
	SDL_Event Event;
	while(non_stop) {
		while(SDL_PollEvent(&Event)) {
			// Scan events
			if(Event.type == SDL_QUIT) non_stop = false;
			if(Event.type == SDL_MOUSEMOTION)	CAMERA->YawPitch( (-(real)Event.motion.xrel)*0.5f, ((real)Event.motion.yrel)*0.5f );
		}

		// Check input from keyboard
		INPUT->Update( 1.0 );
		if( INPUT->IsKeyboardButtonDownDirect( SDLK_ESCAPE ) ) 	non_stop = false;
		if( INPUT->IsKeyboardButtonDownDirect( SDLK_w ) )			CAMERA->StepForward( 0.1, 1.0 );
		else if( INPUT->IsKeyboardButtonDownDirect( SDLK_s ) )	CAMERA->StepForward( -0.1, 1.0 );
		if( INPUT->IsKeyboardButtonDownDirect( SDLK_d ) ) 			CAMERA->StepRight( -0.1, 1.0 );
		else if( INPUT->IsKeyboardButtonDownDirect( SDLK_a ) ) 	CAMERA->StepRight( 0.1, 1.0 );
		if( INPUT->IsKeyboardButtonDownDirect( SDLK_SPACE ) ) 	CAMERA->StepUp( 0.1, 1.0 );
		else if( INPUT->IsKeyboardButtonDownDirect( SDLK_LCTRL ) ) 	CAMERA->StepUp( -0.1, 1.0 );

		// Update Game Here
		counter++;
		if( counter == 100 )
			counter = 0;
		real animation = ((real)counter)*0.01;

		// Render Graphics Here
		BACKBUFFER->SetView( NULL );

		BACKBUFFER->Begin( );
			BACKBUFFER->Clear( );

			BACKBUFFER->BeginPrimitive( VPT_QUADS );
				BACKBUFFER->RenderVertex( vec3r( 1, 1, -3 ) );
				BACKBUFFER->RenderVertex( vec3r( 2, 1, -3 ) );
				BACKBUFFER->RenderVertex( vec3r( 2, 2, -3 ) );
				BACKBUFFER->RenderVertex( vec3r( 1, 2, -3 ) );
			BACKBUFFER->EndPrimitive( );
			BACKBUFFER->BeginPrimitive( VPT_LINES );
				real Y = -1;
				int alongX = 20;
				int alongZ = 20;
				for( int ix = 0; ix < alongX; ix++ ) {
					BACKBUFFER->RenderVertex( vec3r( ix - 10 + animation, Y, -alongZ/2 ), rgba(0.5 + ((real)ix)*0.025,0,0) );
					BACKBUFFER->RenderVertex( vec3r( ix - 10 + animation, Y, +alongZ/2 ), rgba(0.5 + ((real)ix)*0.025,1,0) );
				}
				for( int iz = 0; iz < alongZ; iz++ ) {
					BACKBUFFER->RenderVertex( vec3r( +alongX/2, Y, iz - 10 - animation ), rgba(0,0.5 + ((real)iz)*0.025,0) );
					BACKBUFFER->RenderVertex( vec3r( -alongX/2, Y, iz - 10 - animation ), rgba(0,0.5 + ((real)iz)*0.025,1) );
				}
			BACKBUFFER->EndPrimitive( );

         buffer->Bind( );
         buffer->Draw( );

		BACKBUFFER->End( );


		// Swap buffers
		RENDERER->Present( );
	}

	/// CLEANUP
	FREE( RENDERER )
	return 0;
}
